package com.hnzbxy.api.biz.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hnzbxy.api.biz.converter.ClassInfoConverter;
import com.hnzbxy.api.biz.entity.ClassAdvisor;
import com.hnzbxy.api.biz.entity.ClassInfo;
import com.hnzbxy.api.biz.entity.Teacher;
import com.hnzbxy.api.biz.mapper.ClassAdvisorMapper;
import com.hnzbxy.api.biz.mapper.ClassInfoMapper;
import com.hnzbxy.api.biz.mapper.TeacherMapper;
import com.hnzbxy.api.biz.service.ClassInfoService;
import com.hnzbxy.api.biz.vo.ClassInfoVO;
import com.hnzbxy.api.common.bean.ActiveUser;
import com.hnzbxy.api.common.exception.ServiceException;
import com.hnzbxy.api.system.vo.PageVO;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 班级信息Service实现（包含关联数据查询）
 */
@Service
public class ClassInfoServiceImpl implements ClassInfoService {

    @Autowired
    private ClassInfoMapper classInfoMapper;  // 班级表Mapper

    @Autowired
    private TeacherMapper teacherMapper;  // 教员表Mapper

    @Autowired
    private ClassAdvisorMapper classAdvisorMapper;  // 班主任表Mapper

    /**
     * 分页+条件查询班级列表（包含关联数据，且仅显示当前用户负责的班级）
     */
    @Override
    public PageVO<ClassInfoVO> findClassInfoList(Integer pageNum, Integer pageSize, ClassInfoVO classInfoVO) {
        PageHelper.startPage(pageNum, pageSize);

        Example example = new Example(ClassInfo.class);
        Example.Criteria criteria = example.createCriteria();

        // 基础查询条件：班级名称、年级、状态、是否合班
        if (!StringUtils.isEmpty(classInfoVO.getClassName())) {
            criteria.andLike("className", "%" + classInfoVO.getClassName() + "%");
        }
        if (!StringUtils.isEmpty(classInfoVO.getGrade())) {
            criteria.andEqualTo("grade", classInfoVO.getGrade());
        }
        if (classInfoVO.getClassStatus() != null) {
            criteria.andEqualTo("classStatus", classInfoVO.getClassStatus());
        }
        if (classInfoVO.getIsCombined() != null) {
            criteria.andEqualTo("isCombined", classInfoVO.getIsCombined());
        }

        // 1. 获取当前登录用户的手机号
        ActiveUser activeUser = (ActiveUser) SecurityUtils.getSubject().getPrincipal();
        String phoneNumber = activeUser.getUser().getPhoneNumber();
        if (StringUtils.isEmpty(phoneNumber)) {
            // 手机号为空时，无权限查看任何班级（根据业务调整）
            return new PageVO<>(0L, new ArrayList<>());
        }

        // 2. 根据手机号查询用户身份（班主任/教员）
        // 2.1 查询是否为班主任
        ClassAdvisor currentAdvisor = getClassAdvisorByPhone(phoneNumber);
        // 2.2 查询是否为教员
        Teacher currentTeacher = getTeacherByPhone(phoneNumber);

        // 3. 按身份添加班级权限条件（仅显示用户负责的班级）
        boolean hasPermission = false;
        // 3.1 若为班主任：筛选班级表中class_advisor_ids包含该班主任ID的班级
        if (currentAdvisor != null) {
            hasPermission = true;
            Long advisorId = currentAdvisor.getId().longValue(); // 转换为long匹配class_info的bigint类型
            addIdInCommaListCondition(criteria, "class_advisor_ids", advisorId);
        }
        // 3.2 若为教员：筛选班级表中teacher_ids包含该教员ID的班级（使用OR连接）
        if (currentTeacher != null) {
            hasPermission = true;
            Long teacherId = currentTeacher.getId().longValue();
            addIdInCommaListCondition(criteria, "teacher_ids", teacherId);
        }

        // 5. 执行查询并转换结果
        List<ClassInfo> classInfoList = classInfoMapper.selectByExample(example);
        List<ClassInfoVO> voList = ClassInfoConverter.converterToListVO(classInfoList);

        // 处理关联数据（如班主任/教员姓名等）
        setRelationData(voList, classInfoList);

        PageInfo<ClassInfo> pageInfo = new PageInfo<>(classInfoList);
        return new PageVO<>(pageInfo.getTotal(), voList);
    }

    /**
     * 根据手机号查询班主任
     */
    private ClassAdvisor getClassAdvisorByPhone(String phone) {
        Example example = new Example(ClassAdvisor.class);
        example.createCriteria().andEqualTo("phone", phone);
        List<ClassAdvisor> advisors = classAdvisorMapper.selectByExample(example);
        return advisors.isEmpty() ? null : advisors.get(0);
    }

    /**
     * 根据手机号查询教员
     */
    private Teacher getTeacherByPhone(String phone) {
        Example example = new Example(Teacher.class);
        example.createCriteria().andEqualTo("phone", phone);
        List<Teacher> teachers = teacherMapper.selectByExample(example);
        return teachers.isEmpty() ? null : teachers.get(0);
    }

    /**
     * 给条件添加：字段（逗号分隔的ID列表）包含目标ID的查询条件
     * 处理场景：ID在开头（如"1,2,3"）、中间（如"2,1,3"）、结尾（如"2,3,1"）、单独存在（如"1"）
     */
    private void addIdInCommaListCondition(Example.Criteria criteria, String fieldName, Long targetId) {
        String idStr = targetId.toString();
        // 拼接SQL条件：字段 LIKE '%,id,%' OR LIKE 'id,%' OR LIKE '%,id' OR = 'id'
        criteria.orCondition(
                fieldName + " LIKE concat('%,', '" + idStr + "', ',%') OR " +
                        fieldName + " LIKE concat('" + idStr + "', ',%') OR " +
                        fieldName + " LIKE concat('%,', '" + idStr + "') OR " +
                        fieldName + " = '" + idStr + "'"
        );
    }

    /**
     * 按条件查询所有班级（Excel导出用）
     */
    @Override
    public List<ClassInfo> findAllByCondition(ClassInfoVO classInfoVO) {
        Example example = new Example(ClassInfo.class);
        Example.Criteria criteria = example.createCriteria();

        if (!StringUtils.isEmpty(classInfoVO.getClassName())) {
            criteria.andLike("className", "%" + classInfoVO.getClassName() + "%");
        }
        if (!StringUtils.isEmpty(classInfoVO.getGrade())) {
            criteria.andEqualTo("grade", classInfoVO.getGrade());
        }
        if (classInfoVO.getClassStatus() != null) {
            criteria.andEqualTo("classStatus", classInfoVO.getClassStatus());
        }
        if (classInfoVO.getIsCombined() != null) {
            criteria.andEqualTo("isCombined", classInfoVO.getIsCombined());
        }

        List<ClassInfo> classInfoList = classInfoMapper.selectByExample(example);
        return CollectionUtils.isEmpty(classInfoList) ? new ArrayList<>() : classInfoList;
    }

    /**
     * 新增班级
     */
    @Override
    public ClassInfo add(ClassInfoVO classInfoVO) {
        // 处理历任ID组（新增时将当前ID加入历史记录）
        handleHistoryIds(classInfoVO);

        ClassInfo classInfo = ClassInfoConverter.converterToEntity(classInfoVO);
        int insert = classInfoMapper.insert(classInfo);
        if (insert != 1) {
            throw new ServiceException("新增班级失败");
        }
        return classInfo;
    }

    /**
     * 删除班级
     */
    @Override
    public void delete(Long id) {
        ClassInfo classInfo = classInfoMapper.selectByPrimaryKey(id);
        if (classInfo == null) {
            throw new ServiceException("要删除的班级不存在");
        }
        int delete = classInfoMapper.deleteByPrimaryKey(id);
        if (delete != 1) {
            throw new ServiceException("删除班级失败");
        }
    }

    /**
     * 获取班级详情（编辑用，包含关联数据）
     */
    @Override
    public ClassInfoVO edit(Long id) {
        ClassInfo classInfo = classInfoMapper.selectByPrimaryKey(id);
        if (classInfo == null) {
            throw new ServiceException("要编辑的班级不存在");
        }

        ClassInfoVO vo = ClassInfoConverter.converterToVO(classInfo);
        // 处理单个班级的关联数据
        setSingleRelationData(vo, classInfo);

        return vo;
    }

    /**
     * 更新班级信息
     */
    @Override
    public void update(Long id, ClassInfoVO classInfoVO) {
        ClassInfo dbClassInfo = classInfoMapper.selectByPrimaryKey(id);
        if (dbClassInfo == null) {
            throw new ServiceException("要更新的班级不存在");
        }

        // 处理历任ID组（更新时将新的当前ID加入历史记录，去重）
        handleHistoryIdsForUpdate(classInfoVO, dbClassInfo);

        ClassInfo classInfo = ClassInfoConverter.converterToEntity(classInfoVO);
        classInfo.setId(id);
        int update = classInfoMapper.updateByPrimaryKeySelective(classInfo);
        if (update != 1) {
            throw new ServiceException("更新班级信息失败");
        }
    }

    /**
     * 处理批量关联数据
     */
    private void setRelationData(List<ClassInfoVO> voList, List<ClassInfo> classInfoList) {
        // 收集所有需要查询的ID
        Set<Long> allCombinedClassIds = new HashSet<>();
        Set<Long> allTeacherIds = new HashSet<>();
        Set<Long> allAdvisorIds = new HashSet<>();

        for (ClassInfo classInfo : classInfoList) {
            // 收集合班关联班级ID
            allCombinedClassIds.addAll(splitIds(classInfo.getCombinedClassIds()));
            // 收集历任教员ID
            allTeacherIds.addAll(splitIds(classInfo.getTeacherIds()));
            // 收集历任班主任ID
            allAdvisorIds.addAll(splitIds(classInfo.getClassAdvisorIds()));
            // 收集当前班主任ID
            if (classInfo.getCurrentCaId() != null) {
                allAdvisorIds.add(classInfo.getCurrentCaId());
            }
            // 收集当前教员ID
            if (classInfo.getCurrentTcId() != null) {
                allTeacherIds.add(classInfo.getCurrentTcId());
            }
        }

        // 批量查询所有关联数据
        Map<Long, String> classNameMap = batchGetClassNames(new ArrayList<>(allCombinedClassIds));
        Map<Long, String> teacherNameMap = batchGetTeacherNames(new ArrayList<>(allTeacherIds));
        Map<Long, String> advisorNameMap = batchGetAdvisorNames(new ArrayList<>(allAdvisorIds));

        // 为每个VO设置关联名称
        for (int i = 0; i < voList.size(); i++) {
            ClassInfoVO vo = voList.get(i);
            ClassInfo classInfo = classInfoList.get(i);

            // 设置合班关联班级名称
            setCombinedClassNames(vo, classInfo, classNameMap);

            // 设置历任教员名称
            setTeacherNames(vo, classInfo, teacherNameMap);

            // 设置历任班主任名称
            setAdvisorNames(vo, classInfo, advisorNameMap);

            // 设置当前班主任名称
            vo.setCurrentCaName(advisorNameMap.getOrDefault(classInfo.getCurrentCaId(), "未知"));

            // 设置当前教员名称
            vo.setCurrentTcName(teacherNameMap.getOrDefault(classInfo.getCurrentTcId(), "未知"));
        }
    }

    /**
     * 处理单个班级的关联数据
     */
    private void setSingleRelationData(ClassInfoVO vo, ClassInfo classInfo) {
        // 合班关联班级名称
        List<Long> combinedIds = splitIds(classInfo.getCombinedClassIds());
        Map<Long, String> classNameMap = batchGetClassNames(combinedIds);
        setCombinedClassNames(vo, classInfo, classNameMap);

        // 历任教员名称
        List<Long> teacherIds = splitIds(classInfo.getTeacherIds());
        Map<Long, String> teacherNameMap = batchGetTeacherNames(teacherIds);
        setTeacherNames(vo, classInfo, teacherNameMap);

        // 历任班主任名称
        List<Long> advisorIds = splitIds(classInfo.getClassAdvisorIds());
        Map<Long, String> advisorNameMap = batchGetAdvisorNames(advisorIds);
        setAdvisorNames(vo, classInfo, advisorNameMap);

        // 当前班主任名称
        if (classInfo.getCurrentCaId() != null) {
            List<Long> caIds = Collections.singletonList(classInfo.getCurrentCaId());
            Map<Long, String> caNameMap = batchGetAdvisorNames(caIds);
            vo.setCurrentCaName(caNameMap.getOrDefault(classInfo.getCurrentCaId(), "未知"));
        }

        // 当前教员名称
        if (classInfo.getCurrentTcId() != null) {
            List<Long> tcIds = Collections.singletonList(classInfo.getCurrentTcId());
            Map<Long, String> tcNameMap = batchGetTeacherNames(tcIds);
            vo.setCurrentTcName(tcNameMap.getOrDefault(classInfo.getCurrentTcId(), "未知"));
        }
    }

    /**
     * 拆分ID字符串为集合
     */
    private List<Long> splitIds(String ids) {
        if (StringUtils.isEmpty(ids)) {
            return Collections.emptyList();
        }
        return Arrays.stream(ids.split(","))
                .filter(StringUtils::hasText)
                .map(Long::valueOf)
                .collect(Collectors.toList());
    }

    /**
     * 批量查询班级名称
     */
    private Map<Long, String> batchGetClassNames(List<Long> classIds) {
        if (CollectionUtils.isEmpty(classIds)) {
            return Collections.emptyMap();
        }

        Example example = new Example(ClassInfo.class);
        example.createCriteria().andIn("id", classIds);
        List<ClassInfo> classes = classInfoMapper.selectByExample(example);

        return classes.stream()
                .collect(Collectors.toMap(ClassInfo::getId, ClassInfo::getClassName));
    }

    /**
     * 批量查询教员姓名
     */
    private Map<Long, String> batchGetTeacherNames(List<Long> teacherIds) {
        if (CollectionUtils.isEmpty(teacherIds)) {
            return Collections.emptyMap();
        }

        Example example = new Example(Teacher.class);
        example.createCriteria().andIn("id", teacherIds);
        List<Teacher> teachers = teacherMapper.selectByExample(example);

        return teachers.stream()
                .collect(Collectors.toMap(Teacher::getId, Teacher::getName));
    }

    /**
     * 批量查询班主任姓名
     */
    private Map<Long, String> batchGetAdvisorNames(List<Long> advisorIds) {
        if (CollectionUtils.isEmpty(advisorIds)) {
            return Collections.emptyMap();
        }

        Example example = new Example(ClassAdvisor.class);
        example.createCriteria().andIn("id", advisorIds);
        List<ClassAdvisor> advisors = classAdvisorMapper.selectByExample(example);

        return advisors.stream()
                .collect(Collectors.toMap(ClassAdvisor::getId, ClassAdvisor::getName));
    }

    /**
     * 设置合班关联班级名称
     */
    private void setCombinedClassNames(ClassInfoVO vo, ClassInfo classInfo, Map<Long, String> classNameMap) {
        List<Long> combinedIds = splitIds(classInfo.getCombinedClassIds());
        List<String> names = combinedIds.stream()
                .map(classNameMap::get)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        vo.setCombinedClassNames(StringUtils.collectionToCommaDelimitedString(names));
    }

    /**
     * 设置历任教员名称
     */
    private void setTeacherNames(ClassInfoVO vo, ClassInfo classInfo, Map<Long, String> teacherNameMap) {
        List<Long> teacherIds = splitIds(classInfo.getTeacherIds());
        List<String> names = teacherIds.stream()
                .map(teacherNameMap::get)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        vo.setTeacherNames(StringUtils.collectionToCommaDelimitedString(names));
    }

    /**
     * 设置历任班主任名称
     */
    private void setAdvisorNames(ClassInfoVO vo, ClassInfo classInfo, Map<Long, String> advisorNameMap) {
        List<Long> advisorIds = splitIds(classInfo.getClassAdvisorIds());
        List<String> names = advisorIds.stream()
                .map(advisorNameMap::get)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        vo.setClassAdvisorNames(StringUtils.collectionToCommaDelimitedString(names));
    }

    /**
     * 处理新增时的历史ID（将当前ID加入历史记录）
     */
    private void handleHistoryIds(ClassInfoVO classInfoVO) {
        // 处理教员ID历史
        handleTeacherHistoryIds(classInfoVO);

        // 处理班主任ID历史
        handleAdvisorHistoryIds(classInfoVO);
    }

    /**
     * 处理更新时的历史ID（合并新旧ID，去重）
     */
    private void handleHistoryIdsForUpdate(ClassInfoVO classInfoVO, ClassInfo dbClassInfo) {
        // 处理教员ID历史
        handleTeacherHistoryIdsForUpdate(classInfoVO, dbClassInfo);

        // 处理班主任ID历史
        handleAdvisorHistoryIdsForUpdate(classInfoVO, dbClassInfo);
    }

    /**
     * 处理教员历史ID
     */
    private void handleTeacherHistoryIds(ClassInfoVO classInfoVO) {
        Set<Long> teacherIdSet = new LinkedHashSet<>();
        // 如果有当前教员ID，加入历史记录
        if (classInfoVO.getCurrentTcId() != null) {
            teacherIdSet.add(classInfoVO.getCurrentTcId());
        }
        // 转换为逗号分隔字符串
        classInfoVO.setTeacherIds(StringUtils.collectionToCommaDelimitedString(teacherIdSet));
    }

    /**
     * 处理班主任历史ID
     */
    private void handleAdvisorHistoryIds(ClassInfoVO classInfoVO) {
        Set<Long> advisorIdSet = new LinkedHashSet<>();
        // 如果有当前班主任ID，加入历史记录
        if (classInfoVO.getCurrentCaId() != null) {
            advisorIdSet.add(classInfoVO.getCurrentCaId());
        }
        // 转换为逗号分隔字符串
        classInfoVO.setClassAdvisorIds(StringUtils.collectionToCommaDelimitedString(advisorIdSet));
    }

    /**
     * 处理更新时的教员历史ID
     */
    private void handleTeacherHistoryIdsForUpdate(ClassInfoVO classInfoVO, ClassInfo dbClassInfo) {
        Set<Long> teacherIdSet = new LinkedHashSet<>();
        // 添加原有的历史ID
        teacherIdSet.addAll(splitIds(dbClassInfo.getTeacherIds()));
        // 添加新的当前教员ID（如果有变化）
        if (classInfoVO.getCurrentTcId() != null) {
            teacherIdSet.add(classInfoVO.getCurrentTcId());
        }
        // 转换为逗号分隔字符串
        classInfoVO.setTeacherIds(StringUtils.collectionToCommaDelimitedString(teacherIdSet));
    }

    /**
     * 处理更新时的班主任历史ID
     */
    private void handleAdvisorHistoryIdsForUpdate(ClassInfoVO classInfoVO, ClassInfo dbClassInfo) {
        Set<Long> advisorIdSet = new LinkedHashSet<>();
        // 添加原有的历史ID
        advisorIdSet.addAll(splitIds(dbClassInfo.getClassAdvisorIds()));
        // 添加新的当前班主任ID（如果有变化）
        if (classInfoVO.getCurrentCaId() != null) {
            advisorIdSet.add(classInfoVO.getCurrentCaId());
        }
        // 转换为逗号分隔字符串
        classInfoVO.setClassAdvisorIds(StringUtils.collectionToCommaDelimitedString(advisorIdSet));
    }
}
